﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EasyTrader.Option
{
    using OpStateList = List<EasyTrader.Option.StateWatcher>;
    using PriceSignalList = List<EasyTrader.Signal.PriceSignal>;
    using OptValList = List<EasyTrader.Option.OptValItem>;

    using OptSigList = List<EasyTrader.Option.OptSignal>;

    public class StateWatcherList
    {
        private PriceSignalList m_BreakDownSignalList = new PriceSignalList();
        private PriceSignalList m_BreakUpSignalList = new PriceSignalList();
        private OptValList m_DownList = new OptValList();
        private OptValList m_UpList = new OptValList();

        private OptSigList m_HighBeginList = new OptSigList();
        private OptSigList m_LowBeginList = new OptSigList();
        private OpStateList m_HighBeginStateList = new OpStateList();
        private OpStateList m_LowBeginStateList = new OpStateList();

        private int m_OptSigGPCount = 0;
        public int OptSigGPCount
        {
            get { return m_OptSigGPCount; }
            set { m_OptSigGPCount = value; }
        }
        private int m_OptSigMHCount = 0;
        public int OptSigMHCount
        {
            get { return m_OptSigMHCount; }
            set { m_OptSigMHCount = value; }
        }
        private int m_OptSigMPCount = 0;
        public int OptSigMPCount
        {
            get { return m_OptSigMPCount; }
            set { m_OptSigMPCount = value; }
        }
        public void ClearOptValList()
        {
            m_DownList.Clear();
        }

        

        public int CheckOverHighCount()
        {
            int count = m_HighBeginStateList.Count;
            if (count == 0)
                return 0;

            int overCount = 0;
            for (int i = 0; i < count; i++)
            {
                EasyTrader.Option.StateWatcher curWatcher = m_HighBeginStateList[i];
                if (curWatcher.OverSignal.SigType == GlobalVar.OpSignalOverHigh)
                    overCount++;
            }

            return overCount;
        }

        public int CheckUnderLowCount()
        {
            int count = m_LowBeginStateList.Count;
            if (count == 0)
                return 0;

            int underCount = 0;
            for (int i = 0; i < count; i++)
            {
                EasyTrader.Option.StateWatcher curWatcher = m_LowBeginStateList[i];
                if (curWatcher.OverSignal.SigType == GlobalVar.OpSignalUnderLow)
                    underCount++;
            }

            return underCount;
        }

        public EasyTrader.Option.OptSignal GetFirstHighBeginSignal()
        {
            int count = m_HighBeginList.Count;

            if (count == 0)
                return null;

            return m_HighBeginList[count - 1];
        }

        public EasyTrader.Option.OptSignal GetFirstLowBeginSignal()
        {
            int count = m_LowBeginList.Count;

            if (count == 0)
                return null;

            return m_LowBeginList[count - 1];
        }


        public int CollectHighBeginSignal(int a_Mode)
        {
            m_HighBeginList.Clear();
            m_HighBeginStateList.Clear();
            m_OptSigGPCount = 0;
            m_OptSigMHCount = 0;
            m_OptSigMPCount = 0;
            // 내가 우선으로 조사를 한다.
            // 콜은 작은 값이 내가, 풋은 큰값이 내가이다.
            if (a_Mode == GlobalVar.OpCallMode)
            {
                for (int i = 0; i < m_StateList.Count; i++)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    EasyTrader.Option.OptSignal curSignal = curWatcher.Signal;
                    if (curSignal.SigType == GlobalVar.OpSignalHighBeginGP ||
                        curSignal.SigType == GlobalVar.OpSignalHighBeginMH ||
                        curSignal.SigType == GlobalVar.OpSignalHighBeginMP)
                    {
                        if (curSignal.SigType == GlobalVar.OpSignalHighBeginGP)
                            m_OptSigGPCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalHighBeginMH)
                            m_OptSigMHCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalHighBeginMP)
                            m_OptSigMPCount++;
                        m_HighBeginStateList.Add(curWatcher);
                        m_HighBeginList.Add(curSignal);
                    }
                }
            }
            else if (a_Mode == GlobalVar.OpPutMode)
            {
                for (int i = m_StateList.Count - 1; i >= 0; i--)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    EasyTrader.Option.OptSignal curSignal = curWatcher.Signal;
                    if (curSignal.SigType == GlobalVar.OpSignalHighBeginGP ||
                        curSignal.SigType == GlobalVar.OpSignalHighBeginMH ||
                        curSignal.SigType == GlobalVar.OpSignalHighBeginMP)
                    {
                        if (curSignal.SigType == GlobalVar.OpSignalHighBeginGP)
                            m_OptSigGPCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalHighBeginMH)
                            m_OptSigMHCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalHighBeginMP)
                            m_OptSigMPCount++;
                        m_HighBeginStateList.Add(curWatcher);
                        m_HighBeginList.Add(curSignal);
                    }
                }
            }

            return m_HighBeginList.Count;
        }

        public int CollectLowBeginSignal(int a_Mode)
        {
            m_LowBeginList.Clear();
            m_LowBeginStateList.Clear();
            m_OptSigGPCount = 0;
            m_OptSigMHCount = 0;
            m_OptSigMPCount = 0;

            // 내가 우선으로 조사를 한다.
            // 콜은 작은 값이 내가, 풋은 큰값이 내가이다.
            if (a_Mode == GlobalVar.OpCallMode)
            {
                for (int i = 0; i < m_StateList.Count; i++)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    EasyTrader.Option.OptSignal curSignal = curWatcher.Signal;
                    if (curSignal.SigType == GlobalVar.OpSignalLowBeginGP ||
                        curSignal.SigType == GlobalVar.OpSignalLowBeginMH ||
                        curSignal.SigType == GlobalVar.OpSignalLowBeginMP)
                    {
                        if (curSignal.SigType == GlobalVar.OpSignalLowBeginGP)
                            m_OptSigGPCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalLowBeginMH)
                            m_OptSigMHCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalLowBeginMP)
                            m_OptSigMPCount++;
                        m_LowBeginList.Add(curSignal);
                        m_LowBeginStateList.Add(curWatcher);
                    }
                }
            }
            else if (a_Mode == GlobalVar.OpPutMode)
            {
                for (int i = m_StateList.Count - 1; i >= 0; i--)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    EasyTrader.Option.OptSignal curSignal = curWatcher.Signal;
                    if (curSignal.SigType == GlobalVar.OpSignalLowBeginGP ||
                        curSignal.SigType == GlobalVar.OpSignalLowBeginMH ||
                        curSignal.SigType == GlobalVar.OpSignalLowBeginMP)
                    {
                        if (curSignal.SigType == GlobalVar.OpSignalLowBeginGP)
                            m_OptSigGPCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalLowBeginMH)
                            m_OptSigMHCount++;
                        if (curSignal.SigType == GlobalVar.OpSignalLowBeginMP)
                            m_OptSigMPCount++;
                        m_LowBeginList.Add(curSignal);
                        m_LowBeginStateList.Add(curWatcher);
                    }
                }
            }

            return m_LowBeginList.Count;
        }

        public void AddOptVal(string a_Code, double a_Val)
        {
            EasyTrader.Option.OptValItem optVal = new EasyTrader.Option.OptValItem();
            optVal.Code = a_Code;
            optVal.Val = a_Val;

            // 이전 신호와 중복 검사를 한다.
            if (FindItem(a_Code, a_Val) == false)
                m_DownList.Add(optVal);
        }

        public int GetOptValCount()
        {
            return m_DownList.Count;
        }

        public EasyTrader.Option.OptValItem GetPrevOptValItem()
        {
            if (m_DownList.Count < 2)
                return null;

            return m_DownList[m_DownList.Count - 2];
        }

        private bool FindItem(string a_Code, double a_Val)
        {
            int count = m_DownList.Count;
            if (count == 0)
                return false;

            for (int i = count - 1; i >= 0; i--)
            {
                EasyTrader.Option.OptValItem item = m_DownList[i];
                if (item.Code == a_Code && item.Val == a_Val)
                    return true;
            }

            return false;
        }

        public EasyTrader.Signal.PriceSignal FindBreakDownSignal(int a_CurIndex)
        {
            EasyTrader.Signal.PriceSignal curSignal = null;
            // 콜과 풋은 서로 입장이 다르다
            // 콜이든 풋이든 시스템 모드에 상관없이 내가 우선으로 한다.
            // 내가는 상당히 중요한 의미를 지니기 때문이다.
            if (m_CallPutMode == GlobalVar.OpCallMode)
            {
                // 내가 부터 - 콜은 행사가가 작은 것이 내가 이다.
                for (int i = 0; i < m_StateList.Count; i++)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    curSignal = curWatcher.FindSignal(a_CurIndex, GlobalVar.OpSignalModeBreakDown);
                    if (curSignal != null)
                    {
                        curSignal = CheckAddSignal(m_BreakDownSignalList, curSignal);
                        if (curSignal != null)
                            break;
                    }
                }
            }
            else if (m_CallPutMode == GlobalVar.OpPutMode)
            {
                // 내가 부터 - 풋은 행사가가 큰 것이 내가 이다.
                for (int i = m_StateList.Count - 1; i >= 0; i--)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    curSignal = curWatcher.FindSignal(a_CurIndex, GlobalVar.OpSignalModeBreakDown);
                    if (curSignal != null)
                    {
                        curSignal = CheckAddSignal(m_BreakDownSignalList, curSignal);
                        if (curSignal != null)
                            break;
                    }
                }
            }
            if (curSignal != null)
                return curSignal;
            else
                return null;
        }

        public EasyTrader.Signal.PriceSignal CheckAddSignal(PriceSignalList a_SignalList, EasyTrader.Signal.PriceSignal a_Signal)
        {
            if (a_Signal == null || a_SignalList == null)
                return null;
            int count = a_SignalList.Count;

            EasyTrader.Signal.PriceSignal newSignal = null;
            if (count <= 0)
            {
                newSignal = a_Signal.Clone();
                a_SignalList.Add(newSignal);
                return newSignal;
            }
            else
            {
                EasyTrader.Signal.PriceSignal prevSignal = a_SignalList[count - 1];
                if (prevSignal.OptSigCode != a_Signal.OptSigCode)
                {
                    newSignal = a_Signal.Clone();
                    a_SignalList.Add(newSignal);
                    return newSignal;
                }
                else
                {
                    if (prevSignal.OptSigType != a_Signal.OptSigType)
                    {
                        newSignal = a_Signal.Clone();
                        a_SignalList.Add(newSignal);
                        return newSignal;
                    }
                    else
                    {
                        if (prevSignal.OptSigVal != a_Signal.OptSigVal)
                        {
                            newSignal = a_Signal.Clone();
                            a_SignalList.Add(newSignal);
                            return newSignal;
                        }
                    }
                }
            }

            return null;
        }

        public EasyTrader.Signal.PriceSignal FindBreakUpSignal(int a_CurIndex)
        {
            EasyTrader.Signal.PriceSignal curSignal = null;
            // 콜과 풋은 서로 입장이 다르다
            // 콜이든 풋이든 시스템 모드에 상관없이 내가 우선으로 한다.
            // 내가는 상당히 중요한 의미를 지니기 때문이다.
            if (m_CallPutMode == GlobalVar.OpCallMode)
            {
                // 내가 부터 - 콜은 행사가가 작은 것이 내가 이다.
                for (int i = 0; i < m_StateList.Count; i++)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    curSignal = curWatcher.FindSignal(a_CurIndex, GlobalVar.OpSignalModeBreakUp);
                    if (curSignal != null)
                    {
                        curSignal = CheckAddSignal(m_BreakUpSignalList, curSignal);
                    }
                }
            }
            else if (m_CallPutMode == GlobalVar.OpPutMode)
            {
                // 내가 부터 - 풋은 행사가가 큰 것이 내가 이다.
                for (int i = m_StateList.Count - 1; i >= 0; i--)
                {
                    StateWatcher curWatcher = m_StateList[i];
                    curSignal = curWatcher.FindSignal(a_CurIndex, GlobalVar.OpSignalModeBreakUp);
                    if (curSignal != null)
                    {
                        curSignal = CheckAddSignal(m_BreakUpSignalList, curSignal);
                    }
                }
            }
            return curSignal;
        }

        private int m_BreakDownCount = 0;
        public int BreakDownCount
        {
            get { return m_BreakDownCount; }
            set { m_BreakDownCount = value; }
        }
        private int m_BreakUpCount = 0;
        public int BreakUpCount
        {
            get { return m_BreakUpCount; }
            set { m_BreakUpCount = value; }
        }

        public StateWatcherList(int a_CallPutMode)
        {
            m_CallPutMode = a_CallPutMode;
        }

        private int m_SignalMode = GlobalVar.OpSignalModeNone;
        public int SignalMode
        {
            get { return m_SignalMode; }
            set { m_SignalMode = value; }
        }

        private int m_CallPutMode = GlobalVar.OpCallPutModeNone;
        public int CallPutMode
        {
            get { return m_CallPutMode; }
            set { m_CallPutMode = value; }
        }
        //private EasyTrader.Option.CompVal m_FirstBreakVal = null;

        private int m_StartTime = 0;
        public int StartTime
        {
            get { return m_StartTime; }
            set { m_StartTime = value; }
        }

        /*
        private List<EasyTrader.Option.CompVal> m_FirstBreakList = new List<EasyTrader.Option.CompVal>();
	    public List<EasyTrader.Option.CompVal> FirstBreakList
	    {
		    get { return m_FirstBreakList; }
		    set { m_FirstBreakList = value; }
	    }*/
        

        // 최초로 붕괴한 값들만 모아놓은 목록 
        private List<EasyTrader.Option.CompVal> m_FirstUpList = new List<EasyTrader.Option.CompVal>();
	    public List<EasyTrader.Option.CompVal> FirstUpList
	    {
		    get { return m_FirstUpList; }
		    set { m_FirstUpList = value; }
	    }

        private List<EasyTrader.Option.CompVal> m_FirstDownList = new List<EasyTrader.Option.CompVal>();
	    public List<EasyTrader.Option.CompVal> FirstDownList
	    {
		    get { return m_FirstDownList; }
		    set { m_FirstDownList = value; }
	    }
       
        private List<EasyTrader.Option.CompVal> m_SigUpList = new List<EasyTrader.Option.CompVal>();
	    public List<EasyTrader.Option.CompVal> SigUpList
	    {
		    get { return m_SigUpList; }
		    set { m_SigUpList = value; }
	    }
        private List<EasyTrader.Option.CompVal> m_SigDownList = new List<EasyTrader.Option.CompVal>();
	    public List<EasyTrader.Option.CompVal> SigDownList
	    {
		    get { return m_SigDownList; }
		    set { m_SigDownList = value; }
	    }


        public EasyTrader.Signal.PriceSignal GetRecentBreakDownSignal()
        {
            int count = m_BreakDownSignalList.Count;

            if (count == 0)
                return null;

            return m_BreakDownSignalList[count - 1];
        }

        public EasyTrader.Signal.PriceSignal GetRecentBreakUpSignal()
        {
            int count = m_BreakUpSignalList.Count;

            if (count == 0)
                return null;

            return m_BreakUpSignalList[count - 1];
        }

        public EasyTrader.Option.CompVal GetLastSigDownVal()
        {
            if (m_SigDownList.Count == 0)
                return null;

            return m_SigDownList[m_SigDownList.Count - 1];
        }

        public EasyTrader.Option.CompVal GetLastSigUpVal()
        {
            if (m_SigUpList.Count == 0)
                return null;

            return m_SigUpList[m_SigUpList.Count - 1];
        }

        // 상방의 목표가를 순서대로 늘어 놓은 목록
        // 목표가와 현재가의 차이가 0보다 큰 값들만 모아놓은 목록
        private List<CompVal> m_UpTargetList = new List<CompVal>();
        public List<CompVal> UpTargetList
        {
            get { return m_UpTargetList; }
            set { m_UpTargetList = value; }
        }
        // 하방의 붕괴가를 순서대로 늘어 놓은 목록
        // 목표가와 현재가의 차이가 0보다 작거나 같은 값들만 모아 놓은 목록
        private List<CompVal> m_DownTargetList = new List<CompVal>();
        public List<CompVal> DownTargetList
        {
            get { return m_DownTargetList; }
            set { m_DownTargetList = value; }
        }

        
        /*
        public void CollectBreakUpDownList(string a_SideCode, EasyTrader.Option.CompVal a_LastBreakDownVal, EasyTrader.Option.CompVal a_LastBreakUpVal)
        {
            m_UpList.Clear();
            m_DownList.Clear();
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                List<CompVal> valList = curWatcher.ComValList;
                for (int j = 0; j < valList.Count; j++)
                {
                    EasyTrader.Option.CompVal curVal = valList[j];
                    string sideCode = curVal.BreakCode.Substring(0, 1);
                    if (sideCode == a_SideCode)
                    {
                        if (curVal.State == GlobalVar.BreakUp)
                            m_UpList.Add(curVal);
                        if (curVal.State == GlobalVar.BreakDown)
                            m_DownList.Add(curVal);
                    }
                }
            }
            EasyTrader.Option.SortOnBreakTimeAscend SBA = new EasyTrader.Option.SortOnBreakTimeAscend();
            m_UpList.Sort(SBA);
            if (m_UpList.Count > 0)
            {
                a_LastBreakUpVal = m_UpList[m_UpList.Count - 1];
            }
            m_DownList.Sort(SBA);
            if (m_DownList.Count > 0)
            {
                a_LastBreakDownVal = m_DownList[m_DownList.Count - 1];
            }
        }
        */

        public void CollectBreakUpDownList(string a_SideCode)
        {
            m_SigUpList.Clear();
            m_SigDownList.Clear();
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                List<CompVal> valList = curWatcher.ComValList;
                for (int j = 0; j < valList.Count; j++)
                {
                    EasyTrader.Option.CompVal curVal = valList[j];
                    string sideCode = curVal.BreakCode.Substring(0, 1);
                    if (sideCode == a_SideCode)
                    {
                        if (curVal.RecentState == GlobalVar.BreakUp)
                            m_SigUpList.Add(curVal);
                        if (curVal.RecentState == GlobalVar.BreakDown)
                            m_SigDownList.Add(curVal);
                    }
                }
            }

            if (a_SideCode == "2")
            {
                // 콜일 경우 붕괴되는 값은 시간이 같을 경우 작은값부터 우선으로 정렬한다.
                // 237, 245가 동시에 붕괴되었을 경우 237이 먼저 한다.
                // 이렇게 하는 이유는 행사값이 작은 값이 먼저 무너졌다는게 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceAValD SAD = new EasyTrader.Option.SortOnFTimeAPriceAValD();
                m_SigDownList.Sort(SAD);
                // 돌파되는 경우는 큰값부터 우선으로 정렬한다.
                // 작은 값보다 큰 값이 돌파되기 더 어려우므로 큰 값이 움직였다는데 더 큰 의미를 두기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceDValA SAA = new EasyTrader.Option.SortOnFTimeAPriceDValA();
                m_SigUpList.Sort(SAA);
            }
            else if (a_SideCode == "3")
            {
                // 풋일 경우 붕괴되는 값은 시간이 같을 경우 큰값 우선으로 정렬한다. 
                // 큰 값이 먼저오고 작은 값이 나중에 온다. 245, 237 중 245가 먼저 오고 237이 나중에 온다.
                // 이렇게 하는 이유는 둘이 동시에 붕괴되었을 때 처음에서 값이 높은 놈이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceDValD SAA = new EasyTrader.Option.SortOnFTimeAPriceDValD();
                m_SigDownList.Sort(SAA);
                // 돌파되는 경우는 작은 값 우선으로 정렬한다.
                // 이렇게 하는 이유는 돌파될 때는 작은 값이 돌파한 것 보다 큰 값이 돌파한 것이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceAValA SAD = new EasyTrader.Option.SortOnFTimeAPriceAValA();
                m_SigUpList.Sort(SAD);
            }
        }
        

        public void CollectFirstBreakUpDownList(string a_SideCode, ref EasyTrader.Option.CompVal a_LastBreakDownVal, ref EasyTrader.Option.CompVal a_LastBreakUpVal)
        {
            m_FirstUpList.Clear();
            m_FirstDownList.Clear();
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                List<CompVal> valList = curWatcher.ComValList;
                for (int j = 0; j < valList.Count; j++)
                {
                    EasyTrader.Option.CompVal curVal = valList[j];
                    string sideCode = curVal.BreakCode.Substring(0, 1);
                    if (sideCode == a_SideCode)
                    {
                        if (curVal.FirstState == GlobalVar.BreakUp)
                            m_FirstUpList.Add(curVal);
                        if (curVal.FirstState == GlobalVar.BreakDown)
                            m_FirstDownList.Add(curVal);
                    }
                }
            }

            if (a_SideCode == "2")
            {
                // 콜일 경우 붕괴되는 값은 시간이 같을 경우 작은값부터 우선으로 정렬한다.
                // 237, 245가 동시에 붕괴되었을 경우 237이 먼저 한다.
                // 이렇게 하는 이유는 행사값이 작은 값이 먼저 무너졌다는게 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceAValD SAD = new EasyTrader.Option.SortOnFTimeAPriceAValD();
                m_FirstDownList.Sort(SAD);
                // 돌파되는 경우는 큰값부터 우선으로 정렬한다.
                // 작은 값보다 큰 값이 돌파되기 더 어려우므로 큰 값이 움직였다는데 더 큰 의미를 두기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceDValA SAA = new EasyTrader.Option.SortOnFTimeAPriceDValA();
                m_FirstUpList.Sort(SAA);
            }
            else if (a_SideCode == "3")
            {
                // 풋일 경우 붕괴되는 값은 시간이 같을 경우 큰값 우선으로 정렬한다. 
                // 큰 값이 먼저오고 작은 값이 나중에 온다. 245, 237 중 245가 먼저 오고 237이 나중에 온다.
                // 이렇게 하는 이유는 둘이 동시에 붕괴되었을 때 처음에서 값이 높은 놈이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceDValD SAA = new EasyTrader.Option.SortOnFTimeAPriceDValD();
                m_FirstDownList.Sort(SAA);
                // 돌파되는 경우는 작은 값 우선으로 정렬한다.
                // 이렇게 하는 이유는 돌파될 때는 작은 값이 돌파한 것 보다 큰 값이 돌파한 것이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceAValA SAD = new EasyTrader.Option.SortOnFTimeAPriceAValA();
                m_FirstUpList.Sort(SAD);
            }

            // 최초의 값을 가져온다.
            if (m_FirstUpList.Count > 0)
            {
                a_LastBreakUpVal = m_FirstUpList[0];
            }
            if (m_FirstDownList.Count > 0)
            {
                a_LastBreakDownVal = m_FirstDownList[0];
            }
        }

        public EasyTrader.Option.CompVal GetFirstBreakVal(string a_SideCode)
        {
            m_FirstUpList.Clear();
            m_FirstDownList.Clear();
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                List<CompVal> valList = curWatcher.ComValList;
                for (int j = 0; j < valList.Count; j++)
                {
                    EasyTrader.Option.CompVal curVal = valList[j];
                    string sideCode = curVal.BreakCode.Substring(0, 1);
                    if (sideCode == a_SideCode)
                    {
                        if (curVal.FirstState == GlobalVar.BreakUp || curVal.FirstState == GlobalVar.Support)
                            m_FirstUpList.Add(curVal);
                        if (curVal.FirstState == GlobalVar.BreakDown || curVal.FirstState == GlobalVar.Resist)
                            m_FirstDownList.Add(curVal);
                    }
                }
            }

            EasyTrader.Option.CompVal breakDownVal = null;
            EasyTrader.Option.CompVal breakUpVal = null;
            EasyTrader.Option.CompVal breakVal = null;
            if (a_SideCode == "2")
            {
                // 콜일 경우 붕괴되는 값은 시간이 같을 경우 작은값부터 우선으로 정렬한다.
                // 237, 245가 동시에 붕괴되었을 경우 237이 먼저 한다.
                // 이렇게 하는 이유는 행사값이 작은 값이 먼저 무너졌다는게 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceAValD SAD = new EasyTrader.Option.SortOnFTimeAPriceAValD();
                m_FirstDownList.Sort(SAD);
                // 돌파되는 경우는 큰값부터 우선으로 정렬한다.
                // 작은 값보다 큰 값이 돌파되기 더 어려우므로 큰 값이 움직였다는데 더 큰 의미를 두기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceDValA SAA = new EasyTrader.Option.SortOnFTimeAPriceDValA();
                m_FirstUpList.Sort(SAA);
                // 최초의 값을 가져온다.
                if (m_FirstUpList.Count > 0)
                {
                    breakUpVal = m_FirstUpList[0];
                }
                if (m_FirstDownList.Count > 0)
                {
                    breakDownVal = m_FirstDownList[0];
                }

                // 가장 최근에 붕괴하거나 돌파한 값을 찾는다.
                if (breakUpVal == null)
                {
                    breakVal = breakDownVal;
                }
                else
                {
                    if (breakDownVal == null)
                        breakVal = breakUpVal;
                    else
                    {
                        if (breakDownVal.FirstBreakTime < breakUpVal.FirstBreakTime)
                            breakVal = breakDownVal;
                        else
                            breakVal = breakUpVal;
                    }
                }
            }
            else if (a_SideCode == "3")
            {
                // 풋일 경우 붕괴되는 값은 시간이 같을 경우 큰값 우선으로 정렬한다. 
                // 큰 값이 먼저오고 작은 값이 나중에 온다. 245, 237 중 245가 먼저 오고 237이 나중에 온다.
                // 이렇게 하는 이유는 둘이 동시에 붕괴되었을 때 처음에서 값이 높은 놈이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceDValD SAA = new EasyTrader.Option.SortOnFTimeAPriceDValD();
                m_FirstDownList.Sort(SAA);
                // 돌파되는 경우는 작은 값 우선으로 정렬한다.
                // 이렇게 하는 이유는 돌파될 때는 작은 값이 돌파한 것 보다 큰 값이 돌파한 것이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFTimeAPriceAValA SAD = new EasyTrader.Option.SortOnFTimeAPriceAValA();
                m_FirstUpList.Sort(SAD);

                // 최초의 값을 가져온다.
                if (m_FirstUpList.Count > 0)
                {
                    breakUpVal = m_FirstUpList[0];
                }
                if (m_FirstDownList.Count > 0)
                {
                    breakDownVal = m_FirstDownList[0];
                }

                // 가장 최근에 붕괴하거나 돌파한 값을 찾는다.
                if (breakUpVal == null)
                {
                    breakVal = breakDownVal;
                }
                else
                {
                    if (breakDownVal == null)
                        breakVal = breakUpVal;
                    else
                    {
                        if (breakDownVal.FirstBreakTime < breakUpVal.FirstBreakTime)
                            breakVal = breakDownVal;
                        else
                            breakVal = breakUpVal;
                    }
                }
            }

            return breakVal;
        }

        public EasyTrader.Option.CompVal CollectSigFirstBreakList(string a_SideCode, int a_CurIndex, int a_UpDown)
        {
            m_SigUpList.Clear();
            m_SigDownList.Clear();
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                string sideCode = curWatcher.OpCode.Substring(0, 1);
                List<CompVal> valList = curWatcher.ComValList;
                if (a_SideCode == sideCode)
                {
                    for (int j = 0; j < valList.Count; j++)
                    {
                        EasyTrader.Option.CompVal curVal = valList[j];
                        if (curVal.FirstBreakDownState == GlobalVar.BreakDown && curVal.FirstBreakDownTime >= m_StartTime)
                            m_SigDownList.Add(curVal);
                        if (curVal.FirstBreakUpState == GlobalVar.BreakUp && curVal.FirstBreakUpTime >= m_StartTime)
                            m_SigUpList.Add(curVal);
                    }
                }
            }

            // 신호가 발생한 시간 부터 돌파 목록이 만들어지면, 기준에 따라 정렬을 해준다.
            // 값은 낮은 가격부터 돌파하고, 행사가가 같을 때는 내가부터, 

            if (a_SideCode == "2")
            {
                // 콜일 경우 붕괴되는 값은 시간이 같을 경우 작은값부터 우선으로 정렬한다.
                // 237, 245가 동시에 붕괴되었을 경우 237이 먼저 한다.
                // 이렇게 하는 이유는 행사값이 작은 값이 먼저 무너졌다는게 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFBDTimeAPriceAValD SAD = new EasyTrader.Option.SortOnFBDTimeAPriceAValD();
                m_SigDownList.Sort(SAD);
                // 돌파되는 경우는 큰값부터 우선으로 정렬한다.
                // 작은 값보다 큰 값이 돌파되기 더 어려우므로 큰 값이 움직였다는데 더 큰 의미를 두기 때문이다.
                EasyTrader.Option.SortOnFBUTimeAPriceDValA SAA = new EasyTrader.Option.SortOnFBUTimeAPriceDValA();
                m_SigUpList.Sort(SAA);
            }
            else if (a_SideCode == "3")
            {
                // 풋일 경우 붕괴되는 값은 시간이 같을 경우 큰값 우선으로 정렬한다. 
                // 큰 값이 먼저오고 작은 값이 나중에 온다. 245, 237 중 245가 먼저 오고 237이 나중에 온다.
                // 이렇게 하는 이유는 둘이 동시에 붕괴되었을 때 처음에서 값이 높은 놈이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFBDTimeAPriceDValD SAA = new EasyTrader.Option.SortOnFBDTimeAPriceDValD();
                m_SigDownList.Sort(SAA);
                // 돌파되는 경우는 작은 값 우선으로 정렬한다.
                // 이렇게 하는 이유는 돌파될 때는 작은 값이 돌파한 것 보다 큰 값이 돌파한 것이 더 의미가 있기 때문이다.
                EasyTrader.Option.SortOnFBUTimeAPriceAValA SAD = new EasyTrader.Option.SortOnFBUTimeAPriceAValA();
                m_SigUpList.Sort(SAD);
            }

            if (a_UpDown == 1)
            {
                if (m_SigUpList.Count > 0)
                    return m_SigUpList[m_SigUpList.Count - 1];
                else
                    return null;
            }
            else if (a_UpDown == -1)
            {
                if (m_SigDownList.Count > 0)
                    return m_SigDownList[m_SigDownList.Count - 1];
                else
                    return null;
            }
            else
                return null;
        }

       

        public EasyTrader.Option.CompVal FindCompVal(string a_OpCode, double a_Val)
        {
            for (int i = 0; i < m_StateList.Count; i++)
            {
                EasyTrader.Option.StateWatcher curWatcher = m_StateList[i];
                for (int j = 0; j < curWatcher.ComValList.Count; j++)
                {
                    EasyTrader.Option.CompVal curVal = curWatcher.ComValList[j];
                    if (curVal.BreakCode == a_OpCode && curVal.Val == a_Val)
                        return curVal;
                }
            }

            return null;
        }


        public void ClearBreakVal()
        {
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                curWatcher.BreakVal = null;
            }
        }


        private  OpStateList m_StateList = new OpStateList();
        public OpStateList StateList
        {
            get { return m_StateList; }
            set { m_StateList = value; }
        }

        public EasyTrader.Option.StateWatcher FindStateWatcher(string a_OpCode)
        {
            for (int i = 0; i < m_StateList.Count; i++)
            {
                EasyTrader.Option.StateWatcher curWatcher = m_StateList[i];
                if (curWatcher.OpCode == a_OpCode)
                    return curWatcher;
            }

            return null;
        }

        // 각 행사가의 상태 합을 가져와 그 값을 모두 더하여 그 합을 전달해 준다.
        public int GetStateCount()
        {
            int stateCount = 0;
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                stateCount += curWatcher.GetStateSum();
            }

            return stateCount;
        }

        public void SaveSigValues(int a_CurIndex)
        {
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                curWatcher.SaveSigValues(a_CurIndex);
            }
        }

        // 시작 인덱스를 모두 바꾸어 준다.
        // a_Type : 1 : 돌파, -1 : 붕괴
        public void SetStartIndex(int a_CurIndex, int a_Type)
        {
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];

                curWatcher.SetStartIndex(a_CurIndex, a_Type);
            }
        }

        public void MakeUpDownTargetList()
        {
            m_UpTargetList.Clear();
            m_DownTargetList.Clear();
            for (int i = 0; i < m_StateList.Count; i++)
            {
                StateWatcher curWatcher = m_StateList[i];
                List<CompVal> valList = curWatcher.ComValList;
                for (int j = 0; j < valList.Count; j++)
                {
                    EasyTrader.Option.CompVal curVal = valList[j];
                    if (curVal.DeltaTarget > 0)
                    {
                        m_UpTargetList.Add(curVal);
                    }
                    else
                    {
                        m_DownTargetList.Add(curVal);
                    }
                }
            }

            // 값의 차이에 의해서 순서대로 정렬
            // m_UpTargetList.Reverse(); -> 반대 순서를 원할 때는 위의 함수를 앞의 함수를 이용한다.
            EasyTrader.Option.SortOnDeltaTargetAscend SDA = new EasyTrader.Option.SortOnDeltaTargetAscend();
            EasyTrader.Option.SortOnDeltaTargetDescend SDD = new EasyTrader.Option.SortOnDeltaTargetDescend();
            m_UpTargetList.Sort(SDA);
            m_DownTargetList.Sort(SDD);
        }

        private int m_Date = 0;
        public int Date
        {
            get { return m_Date; }
            set { m_Date = value; }
        }
    }
}
